package com.eightylegs.customer.sample;

import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class URLFunctions {
	public static final int MAX_URL_LENGTH = 500;
    public static final int MIN_URL_LENGTH = 12;
    
	public static boolean eliminateURL(String outLink){
        outLink = outLink.trim();
        if( outLink.equals("") || outLink.contains("(") || outLink.contains(")") || outLink.contains("[") || outLink.contains("]") || outLink.contains("<") || outLink.contains(">") || outLink.equals("") || !outLink.contains("/")
            || !outLink.startsWith("http")
        	|| outLink.length() > MAX_URL_LENGTH
            || outLink.length() < MIN_URL_LENGTH
            || hasBadCharacters(outLink)
            )
                return true;
            else 
                return false;
    }
    
	private static boolean eliminateURLBeforeNormalize(String outLink) {
		outLink = outLink.trim();
		
        if( outLink.startsWith("javascript:") || outLink.startsWith("mailto:") || outLink.startsWith("about:") || outLink.startsWith("ftp:") || outLink.startsWith("#")
        		|| outLink.matches("((?i)(.*?)\\s+\\+\\s*(.+?))|((?i)(.*?)\\s*\\+\\s+(.+?))") //Link with "+" and spaces before and after the sign: more like it's a js
            ) 
        {
            return true;
        }
        else {
            return false;
        }
	}
	
    public static Boolean isCrawlableLink(String link)
    {
        Pattern pat = Pattern.compile("^.+\\.((png)|(jpg)|(jpeg)|(gif)|(bmp)|(tiff)|(ico)|(doc)|(xls)|(ppt)|(pdf)|(txt)|(dll)|(swf)|(mov)|(flv)|(mp3)|(mp4)|(wma)|(wmv)|(wav)|(asf)|(rm)|(ram)|(ra)|(avi)|(mpeg)|(mid)|(mpg)|(css)|(js))$");
        Matcher matcher = pat.matcher(link);
        return !matcher.matches();
    }
    
    public static String preProcessURL(String outLink, URL originalUrl, URL redirectedUrl, boolean allowQueryStrings) {
		outLink = URLFunctions.trimOutLink(outLink);
		if (!outLink.equals("")) {
			if (!eliminateURLBeforeNormalize(outLink)) {
				outLink = URLFunctions.normalizeURL(outLink, originalUrl, redirectedUrl, allowQueryStrings);
				if(!URLFunctions.eliminateURL(outLink)) {	
					if (!outLink.equals(originalUrl.toString())) {
						return outLink;
					}
				}
			}
		}
		return "";
	}
    
    //Return false if there is at least an ASCII > 128
    private static boolean hasBadCharacters(String link) {
    	boolean found = false;
    	int i = 0;
    	while (i < link.length() && !found) {
    		char c = link.charAt( i );
		    int j = (int) c;
		    if (j >= 128) {
		    	found = true;
		    }
		    else {
		    	i++;
		    }
    	}
    	return found;
    }
    
    public static String normalizeURL(String outLink, URL originalUrl, URL redirectedUrl, boolean allowQueryStrings){		
		if (!outLink.toLowerCase().startsWith("http")){
			if (outLink.startsWith("../")) {
				outLink = redirectedUrl.getProtocol() + "://" + redirectedUrl.getHost() + outLink.replaceFirst("..", "");
			}
			else if (outLink.startsWith("/")){
				outLink = redirectedUrl.getProtocol() + "://" + redirectedUrl.getHost() + outLink;
			}
			else {
				//Relative path, 4 scenarios:
				//(1): http://www.aaa.com   -- Link: a.html  --> http://www.aaa.com/a.html
				//(2): http://www.aaa.com/test.html -- Link: a.html --> http://www.aaa.com/a.html
				//(3): http://www.aaa.com/tricky/test.html -- Link: a.html --> http://www.aaa.com/tricky/a.html
				//(4): http://www.aaa.com/tricky -- Link: a.html --> http://www.aaa.com/tricky/a.html
				
				String redirectedUrlString = redirectedUrl.toString();
				while (redirectedUrlString.endsWith("/"))
					redirectedUrlString = redirectedUrlString.substring(0,redirectedUrlString.length()-1); //Remove trailing "/"
				
				char[] chArrayUrl = redirectedUrlString.toCharArray();
				int slashCount = 0;
				for (int i = 0; i < chArrayUrl.length; i++)
					if (chArrayUrl[i] == '/')
							slashCount++;
				if (slashCount <= 2) {	//Case (1)
					outLink = redirectedUrlString + '/' + outLink;
				}
				else {	
					String[] arrayUrl = redirectedUrlString.split("/"); //Since all source URLs have been normalized, there is no trailing "/"
					StringBuilder tempSourceUrlStringBuilder = new StringBuilder();
					int maxLength = arrayUrl.length;
					Pattern pat = Pattern.compile(".+\\..+$");
					Matcher matcher = pat.matcher(arrayUrl[arrayUrl.length-1]);
					if (matcher.matches()){ //Case (2) and (3): if the last element is a page (test.html), skip the last element
						maxLength--; 
					}	
					for (int i = 0; i < maxLength; i++)
						tempSourceUrlStringBuilder.append(arrayUrl[i].toString()).append("/");
					
					outLink = tempSourceUrlStringBuilder.append(outLink).toString();
				}
			}
		}		
		
		if (allowQueryStrings == false) {
			int firstQuestionMarkPos = outLink.indexOf("?");
			if (firstQuestionMarkPos != -1)
				outLink = outLink.substring(0,firstQuestionMarkPos);
		}

		outLink = outLink.replaceAll("\t", " "); //Replace tab by space. Tab is used as delimiter. 
		outLink = outLink.replaceAll(" ", "%20"); //Replace space with ASCII text
		outLink = outLink.replaceAll("&amp;", "&");
		
		if(outLink.contains("#")) {  //Remove anything after #
			outLink = outLink.substring(0, outLink.indexOf("#"));
		}
		
		outLink = outLink.replaceAll("\\\\", "/"); //Replace "\" with "/"
		outLink = outLink.replaceAll("/+", "/"); //Replace one or more "/" with "/"
		outLink = outLink.replaceFirst("/", "//");//For http:/ --> http://
		
		//Remove default pages like default.asp and index.html
		/*
		String regexRemoveDefaultPage = "/((index)|(default)|(INDEX)|(DEFAULT))\\.((html)|(HTML)|(shtml)|(SHTML)|(htm)|(HTM)|(php)|(PHP)|(asp)|(ASP)|(aspx)|(ASPX)|(jsp)|(JSP))$";
		outLink = outLink.replaceAll(regexRemoveDefaultPage, "");
		*/
		
		//3/10/2009: Commented out b/c of redirection problem. Keep trailing /
		/*
		while (outLink.endsWith("/"))
			outLink = outLink.substring(0,outLink.length()-1); //Remove trailing "/"
		*/
		
		return outLink;
	}
	
	
	//Remove ("href=" or "src=" or "<meta....") and quotes
	public static String trimOutLink(String link)
	{	
		link = link.trim();
		if (link.toLowerCase().startsWith("href"))
			link = link.substring(4, link.length());
		else if (link.toLowerCase().startsWith("src"))
			link = link.substring(3, link.length());
		else if (link.toLowerCase().startsWith("<meta")) {  //Example: <meta http-equiv="Refresh" content="0; url=http://www.example.com/">
			int startPos = link.toLowerCase().indexOf("url");
			int endPos = link.toLowerCase().indexOf(">", startPos);
			link = link.substring(startPos + "url".length(), endPos);
		}
		
		link = link.trim();
		if (link.toLowerCase().startsWith("="))
			link = link.substring(1, link.length());
		
		link = link.trim();
		while (link.startsWith("\"") || link.startsWith("'")) {
			link = link.substring(1, link.length());
			link = link.trim();
		}
		
		while (link.endsWith("\"") || link.endsWith("'") || link.endsWith("/")) {
			link = link.substring(0, link.length()-1);
			link = link.trim();
		}
		return link.trim();
	}
}
